// Copyright (c) 2010 Manuel Peinado Gallego <manuel.peinado@gmail.com>
// Distributed under the MIT license

#include "stdafx.h"
#include "WorldBuilder.h"
#include "GeometryFactory.h"
#include "PrimitiveFactory.h"
#include "Mesh.h"


void GeometryFactory::write(std::wostream& os, const Geometry& geo)
{
    // Write shape type
    GeometryType type = geometryToType(geo);
    ASSERT(type != GeometryTypes::Unknown); // Should probably be an exception
    os << (int)type << "\n"; 
    
    if(type == GeometryTypes::Mesh)
    {
        geo.write(os);
    }
    else if(type == GeometryTypes::Primitive)
    {
        const Primitive* prim = dynamic_cast<const Primitive*>(&geo);
        ASSERT(prim);
        PrimitiveFactory::write(os, *prim);
    }
}

ref<Geometry> GeometryFactory::read(std::wistream & is)
{
    // Read shape type
    int aux;
    is >> aux;
    GeometryType type = (GeometryType)aux; 
    ref<Geometry> geo;

    if(type == GeometryTypes::Mesh)
    {
        geo.reset(new Mesh);
        geo->read(is);
    }
    else if(type == GeometryTypes::Primitive)
    {
        geo = PrimitiveFactory::read(is);
    }

    ASSERT(geo != NULL); // Should probably be an exception

    return geo;
}

// ************************************************************************

ref<Geometry> GeometryFactory::geometryFromType(GeometryType type)
{
    switch(type)
    {
    case GeometryTypes::Primitive:
        return ref<Geometry>(new Cube);
    case GeometryTypes::Mesh:
        return ref<Geometry>(new Mesh);
    default:
        ASSERT(0);
        return ref<Geometry>();
    }
}

GeometryType GeometryFactory::geometryToType(const Geometry& shape)
{
    if(dynamic_cast<const Primitive*>(&shape))
    {
        return GeometryTypes::Primitive;
    }
    if(dynamic_cast<const Mesh*>(&shape))
    {
        return GeometryTypes::Mesh;
    }
    return GeometryTypes::Unknown;
}    


//ref<Geometry> GeometryFactory::shapeFromType(GeometryType type)
//{
//    switch(type)
//    {
//    case PrimitiveTypes::Sphere:
//        return ref<Geometry>(new SphereShape);
//    case PrimitiveTypes::Cube:
//        return ref<Geometry>(new Cube);
//    case PrimitiveTypes::Cylinder:
//        return ref<Geometry>(new CylinderShape);
//    default:
//        return ref<Geometry>();
//    }
//}
//
//GeometryType GeometryFactory::geometryToType(const Geometry& shape)
//{
//    if(dynamic_cast<const SphereShape*>(&shape))
//    {
//        return PrimitiveTypes::Sphere;
//    }
//    if(dynamic_cast<const Cube*>(&shape))
//    {
//        return PrimitiveTypes::Cube;
//    }
//    if(dynamic_cast<const CylinderShape*>(&shape))
//    {
//        return PrimitiveTypes::Cylinder;
//    }
//    return PrimitiveTypes::Unknown;
//}    

// ************************************************************************

ref<Geometry> GeometryFactory::geometryFromName(const std::string& name)
{
    return geometryFromType(nameToType(name));
}

std::string GeometryFactory::nameFromGeometry(const Geometry& shape)
{
    return typeToName(geometryToType(shape));
}

// ************************************************************************

//GeometryType GeometryFactory::nameToType(const std::string& name)
//{
//    if(name == "Cylinder")
//    {
//        return PrimitiveTypes::Cylinder;
//    }
//    if(name  == "Sphere")
//    {
//        return PrimitiveTypes::Sphere;
//    }
//    if(name  == "Cube")
//    {
//        return PrimitiveTypes::Cube;
//    }
//    return PrimitiveTypes::Unknown;
//}
//
//std::string GeometryFactory::typeToName(GeometryType type)
//{
//    switch(type)
//    {
//    case PrimitiveTypes::Sphere:
//        return "Sphere";
//    case PrimitiveTypes::Cube:
//        return "Cube";
//    case PrimitiveTypes::Cylinder:
//        return "Cylinder";
//    default:
//        return "Unknown";
//    }
//}
GeometryType GeometryFactory::nameToType(const std::string& name)
{
    if(name == "Primitive")
    {
        return GeometryTypes::Primitive;
    }
    if(name  == "Mesh")
    {
        return GeometryTypes::Mesh;
    }
    return GeometryTypes::Unknown;
}

std::string GeometryFactory::typeToName(GeometryType type)
{
    switch(type)
    {
    case GeometryTypes::Primitive:
        return "Primitive";
    case GeometryTypes::Mesh:
        return "Mesh";
    default:
        return "Unknown";
    }
}
